from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.remote.webdriver import WebElement

from utils.selenium.highlighted import ElementHighlighted


# 查询方法
class FindType:
    id = 1
    name = 2
    class_name = 3
    tag_name = 4
    link_text = 5
    partial_link_text = 6
    xpath = 7
    css = 8


find_dic = {
    FindType.id: '_by_id',
    FindType.class_name: '_by_class_name',
    FindType.tag_name: '_by_tag_name',
    FindType.link_text: '_by_link_text',
    FindType.name: '_by_name',
    FindType.partial_link_text: '_by_partial_link_text',
    FindType.xpath: '_by_xpath',
    FindType.css: '_by_css_selector',
}

find_header = {
    True: 'find_elements',
    False: 'find_element'
}


class FindElement():
    """
    查询数据
    """

    def __init__(self, driver, find_type: FindType, find_key: str, multiple=False, highlighted=True, find_index=None, is_filter_hide_element=True):
        """
        构造方法
        :param perform:
        :param find_type:
        :param find_key:
        :param multiple:
        :param highlighted:
        :param find_index:
        """
        self.driver = driver
        self.find_type = find_type
        self.find_key = find_key
        self.multiple = multiple
        self.highlighted = highlighted
        self.find_index = find_index
        self.is_filter_hide_element = is_filter_hide_element

    @classmethod
    def find_element(cls, driver, find_type: FindType, find_key: str, multiple=False, highlighted=True, find_index=None, is_filter_hide_element=True) -> WebElement or list:
        """
        查找数据
        :param driver:
        :param find_type:
        :param find_key:
        :param multiple:
        :param highlighted:
        :param find_index:
        :param is_filter_hide_element
        """
        find_model = cls(driver, find_type, find_key, multiple, highlighted, find_index, is_filter_hide_element)
        return find_model.find()

    def find(self) -> WebElement or list:
        if self.find_type == FindType.id and self.multiple:
            raise Exception("【id】查询不能查询多个")
        finf_func_name = '%s%s' % (find_header.get(self.multiple), find_dic.get(self.find_type))
        find_func = getattr(self.driver, finf_func_name)
        try:
            find_data = find_func(self.find_key)
            if self.multiple:
                if self.is_filter_hide_element:
                    find_data = [element for element in find_data if element.is_displayed()]
                if self.find_index is not None:
                    if self.find_index >= len(find_data):
                        raise Exception('数组越界，数组长度【%d】，索引【%d】' % (len(find_data), self.find_index))
                    else:
                        find_data = find_data[self.find_index]
            elif self.is_filter_hide_element and not find_data.is_displayed():
                find_data = None
            # if self.highlighted:
            ElementHighlighted.highlighted(self.driver, find_data)
            return find_data
        except NoSuchElementException:
            return None
